from django.http import HttpResponse
from django.shortcuts import render
from slide.models import Slide
from team.models import Team
from news.models import News

# Create your views here.


def index(request):
    # return HttpResponse('hello world')
    # return render(request, 'index.html')
    # 获取Slide(轮播图)的数据
    slides = Slide.objects.all()
    # 计算获取的数据数量，用于自动生成控制圆点的个数（个人理解添加）
    slides_number = [i for i in range(len(slides))]
    # 传递参数到模板页面，要以字典形式编写，左边的slides为模板接收的变量名称
    # 获取团队成员并排序，使用order_by进行排序，根据字段排序，前面加 - 表示倒序
    team = Team.objects.all().order_by('-rank')
    # 获取资讯中心新闻  这次order_by排序前就不加-来倒序了,[:3]表示获取前3个，使用python的切片进行截取

    """
        首先说下下面两个查询的区别，这个在 readme_ORM.md 没有详细说明
        (1) category_id=2
        问：为什么这么写？
        ################
        答：外键查询的常见场景:
        正向查询(从News到Category):
        使用category__字段名语法，例如category__id、category__name。(注：这里是双下划线)
        反向查询(从Category到News):
        可通过模型名小写_set(如category.news_set.all())或related_name参数定义反向关系
         ################
        (2) category_name='美女'
        为什么这样查询会失败？
        参考原因：
        字段引用方式错误 ---
        在News模型中，category字段是ForeignKey类型，指向Category模型。当你尝试通过category_name查询时，Django会直接在News模型中寻找名为category_name的字段，但该字段并不存在。
        正确方式：需要通过外键关系跨表查询Category模型的name字段，使用双下划线语法category__name。
        Django ORM 查询语法规则
        Django的filter()方法中，若要通过关联模型的字段过滤数据，必须使用关联字段__目标字段的格式（双下划线连接）
        。直接使用category_name会被视为当前模型的字段，而非关联模型的字段。
        (3) 问：为什么 category_id 可以，而 category_name 不可以
        进阶一问：根据第(2)点分析，使用 category__name 双下划线可以进行外键查询，那为什么 category_id 一个下划线就可以直接查询
        答：
        在 Django 的模型查询中，`category_id` 可以成功而 `category_name` 失败的根本原因在于**外键字段的底层实现机制**和**Django ORM 的查询规则**。以下是具体分析：
        ---

        ### **1. 外键字段的数据库存储机制**
        在 Django 模型中，当定义外键 `category = models.ForeignKey(Category)` 时：
        - **数据库层面**：Django 会自动在 `News` 表中生成一个名为 `category_id` 的字段（对应 `Category` 表的主键 `id`），用于存储关联记录的物理键值。
        - **ORM 层面**：Django 通过 `category` 属性提供关联对象的便捷访问（如 `news.category.name`），但实际查询时若直接操作外键值，需使用 `category_id` 字段。

        因此，`category_id` 是数据库中真实存在的字段，可以直接用于过滤，而 `category_name` 需要通过外键关系跨表查询。

        ---

        ### **2. 查询语法的本质区别**
        - **`category_id` 查询**：  
        直接操作 `News` 表中的 `category_id` 字段，属于**当前表的字段查询**，无需跨表关联。例如：
        ```python
        News.objects.filter(category_id=2)  # 直接匹配 category_id 字段的值
        ```

        - **`category_name` 查询**：  
        需要从 `News` 表关联到 `Category` 表，再查询 `name` 字段，属于**跨表关联查询**。必须通过双下划线语法 `category__name` 显式声明关联路径：
        ```python
        News.objects.filter(category__name='美女')  # 正确语法：通过外键关联到 Category.name
        ```

        ---

        ### **3. 为何 `category_id` 能直接使用？**
        - **字段可见性**：`category_id` 是外键字段的物理存储字段，在数据库表和 Django 模型中均直接存在，可通过 `news.category_id` 直接访问。
        - **无需关联查询**：直接通过 `category_id` 过滤时，Django 只需在当前表（`News`）中匹配数值，无需额外联表操作，性能更高。

        ---

        ### **4. 对比 `category_name` 的失败原因**
        - **字段不存在**：`News` 表中没有名为 `category_name` 的字段，直接使用会触发 `FieldError`。
        - **跨表查询语法未遵循**：未使用双下划线 `__` 声明外键关联路径，Django 无法解析查询意图。

        ---

        ### **总结**
        - **`category_id` 是物理字段**：直接存在于当前表中，支持直接查询。
        - **`category_name` 是关联字段**：需通过 `category__name` 语法跨表查询。
        - **性能差异**：`category_id` 查询效率更高，适合精确匹配；`category__name` 需要联表，适合基于关联模型属性的过滤。
        
    """
    news = News.objects.filter(category_id=2).order_by('create_time')[:6]
    # news = News.objects.filter(category__name='美女').order_by('create_time')[:3]

    # 获取成功案例内容 使用exclude进行排除过滤，除了美女分类外的其他分类
    cases = News.objects.exclude(category_id=2).order_by('create_time')[:6]
    # 对数据进行去重处理 使用set集合形式来去重 主要用于循环显示分类名称和id
    cases_category_distanct = set([i.category for i in cases])

    return render(request, 'index.html', {'slides': slides,
                                          'slides_number': slides_number,
                                          'team': team,
                                          'news': news,
                                          'cases': cases,
                                          'cases_category_distanct': cases_category_distanct})
